from django.contrib.auth.hashers import check_password
from django.shortcuts import render
from django.http import JsonResponse
from django.utils import timezone
from rest_framework import viewsets
from Photography.serializers import *
from .models import *
from Photography.models import User
from rest_framework.decorators import action
from rest_framework import permissions
from Photography.permissions import IsOwnerOrReadOnly
from rest_framework.views import APIView
from rest_framework.authtoken.models import Token
from django.contrib import auth
from rest_framework.response import Response
from rest_framework.permissions import AllowAny
import oss2
from read_config import read_config
import uuid

# Create your views here.
conf = read_config()
# oss2配置
# 用户账号密码，第三部说明的Access
# 获取的AccessKey
oss2_auth = oss2.Auth(conf.get('oss', 'AccessKey_ID'), conf.get('oss', 'AccessKey_Secret'))
# 这个是需要用特定的地址，不同地域的服务器地址不同，不要弄错了
# 外网-测试环境
endpoint = 'http://oss-cn-chengdu.aliyuncs.com'
# 内网-生生产环境
# ebdpoint = 'http://oss-cn-chengdu-internal.aliyuncs.com'
# 因为我用的是ajax传到后端方法接受的是b字节文件，需要如下配置。 阿里云oss支持更多的方式，下面有链接可以自己根据自己的需求去写
bucket = oss2.Bucket(oss2_auth, endpoint, 'colourphoto')  # 项目名称
# 这个是上传文件后阿里云返回的uri需要拼接下面这个url才可以访问，根据自己情况去写这步
base_file_url = 'https://colourphoto.oss-cn-chengdu.aliyuncs.com/'


# admin首页数据看板
def dashboard(request):
    user_count = User.objects.count()
    album_count = Album.objects.count()
    picture_count = Picture.objects.count()

    context = {'user_count': user_count, 'album_count': album_count, 'picture_count': picture_count}
    return render(request, 'Photography/dashboard.html', context)


def login(request):
    return render(request, 'Photography/login.html')


def index(request):
    return render(request, 'Photography/desk/index.html')


def home(request):
    return render(request, 'Photography/home.html')


def user(request):
    return render(request, 'Photography/user.html')


class LoginViewSet(APIView):
    """登录方法"""

    def post(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')
        login_user = auth.authenticate(username=username, password=password)
        if not login_user:
            return JsonResponse({"code": 300,
                                 "message": "用户名或密码不对!"})
        # 删除原有的Token
        old_token = Token.objects.filter(user=login_user)
        old_token.delete()
        # 创建新的Token
        token = Token.objects.create(user=login_user)
        return JsonResponse({"code": 100,
                             "message": "login success!",
                             "username": login_user.username,
                             "token": token.key})


def reset(request):
    return render(request, 'Photography/reset.html')


class UserView(APIView):
    # authentication_classes = (TokenAuthentication,)  # token认证
    # permission_classes = (IsAuthenticated,)   # IsAuthenticated 仅通过认证的用户
    permission_classes = (AllowAny,)  # 允许所有用户

    def get(self, request, format=None):
        """
        Return a list of all User
        """
        # 获取所有用户
        info = User.objects.all()
        # 通过序列化器的转换（模型转换为JSON）
        serializer = UserSerializer(info, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        """
        create User
        """
        # 接受参数并进行验证
        verify_data = UserSerializer(data=request.data)
        if verify_data.is_valid():
            try:
                User.objects.get(username=verify_data.initial_data.get('username'))
            except User.DoesNotExist:
                verify_data.save()
                # 查询出添加的用户
                userdata = User.objects.filter(username=verify_data.initial_data.get('username'))
                serializer = UserSerializer(userdata, many=True)
                return JsonResponse({"code": 100, "message": "新增用户成功！", "data": serializer.data})
            else:
                return JsonResponse(
                    {"code": 300, 'message': "新增用户失败！",
                     'data': f'{verify_data.initial_data.get("username")}账号已存在'})
        else:
            return JsonResponse(verify_data.errors)

    def put(self, request, format=None):
        pass

    def delete(self, request, format=None):
        verify_data = UserSerializer(data=request.data)
        # 参数校验，只能传id
        # 这里需要实现用is_valid，验证delete方法的参数只能传入id
        # if verify_data.is_valid():
        if 'id' in verify_data.initial_data.keys():
            try:
                update_user = User.objects.get(id=verify_data.initial_data.get('id'), is_active=1)
            except User.DoesNotExist:
                return JsonResponse(
                    {'code': 300, 'message': '删除用户失败！', 'data': '账号不存在'})
            else:
                update_user.is_active = 0
                update_user.save()
                return JsonResponse(
                    {'code': 100, 'message': '删除用户成功！', 'data': '{}账号已删除'.format(update_user.username)})
        else:
            return JsonResponse(
                {'code': 300, 'message': '参数不合法啊！'}
            )


class PictureView(APIView):
    # authentication_classes = (TokenAuthentication,)  # token认证
    # permission_classes = (IsAuthenticated,)   # IsAuthenticated 仅通过认证的用户
    permission_classes = (AllowAny,)  # 允许所有用户

    def get(self, request, *args, **kwargs):
        """
        Return a list of picture
        """
        album_id = request.GET.get('album_id')
        # 根据相册id获取数据
        picture_info = Picture.objects.filter(album_id_id=album_id, status=1)
        # 通过序列化器的转换（模型转换为JSON）
        serializer = PictureSerializer(picture_info, many=True)
        # 前后端分离
        # return JsonResponse({"code": 100, "message": "查询成功！", "data": serializer.data})
        # 不分离
        return render(request, 'Photography/picture.html', {"data": serializer.data})


class UserViewSet(viewsets.ModelViewSet):
    """
    此视图自动提供`list`和`detail`操作。
    eadOnlyModelViewSet类来自动提供默认的“只读”操作
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @action(detail=False, methods=['post'])
    def reset_psd(self, request):
        """detail_routeDRF 3.8已弃用。可以使用actions装饰器"""
        username = request.data.get('username', '')
        old_pwd = request.data.get('password', '')
        new_pwd = request.data.get('new_pwd', '')
        if old_pwd == new_pwd:
            return JsonResponse({"code": 300,
                                 "msg": "新密码不能和旧密码重复"})
        else:
            try:
                # ****************有加密******************************************************
                # 查询用户得密码
                user_data = User.objects.get(username=username)
                pd = user_data.password
                is_psd_ture = check_password(old_pwd, pd)
                if is_psd_ture:
                    user_data.password = make_password(new_pwd)
                    user_data.save()
                    res = '修改密码成功'
                    return JsonResponse({"code": 100, 'msg': res})
                else:
                    res = '用户名或密码错误'
                    return JsonResponse({"code": 300, 'msg': res})
            except User.DoesNotExist:
                res = '用户名或密码错误'
                return JsonResponse({"code": 300, 'msg': res})

    def create(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')
        email = request.POST.get('email')
        try:
            User.objects.get(username=username)
        except User.DoesNotExist:
            now = timezone.now()
            # make_password对密码加密
            user_data = User.objects.create_user(username=username, password=password, email=email)
            user_data.save()
            return JsonResponse({"code": 100, "msg": "添加成功", "data": {"username": username}})
        else:
            resp = {'code': 300, 'msg': f'{username}账号已存在'}
            return JsonResponse(resp)

    # def perform_create(self, serializer):
    #    serializer.save(owner=self.request.user)


class AlbumViewSet(viewsets.ModelViewSet):
    """
    此视图自动提供`list`，`create`，`retrieve`，`update`和`destroy`操作。
    """
    queryset = Album.objects.all()
    serializer_class = AlbumSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                          IsOwnerOrReadOnly,)

    # 相册加密
    @action(detail=True, methods=['post'])
    def set_password(self, request, pk=None):
        """detail_routeDRF 3.8已弃用。可以使用actions装饰器"""
        pass

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)


class PictureViewSet(viewsets.ModelViewSet):
    """
    此视图自动提供`list`，`create`，`retrieve`，`update`和`destroy`操作。
    """
    queryset = Picture.objects.all()
    serializer_class = PictureSerializer

    # permission_classes = (permissions.IsAuthenticatedOrReadOnly,
    #                      IsOwnerOrReadOnly,)


class UploadFile(APIView):
    """
    上传文件接口
    """
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def post(self, request, *args, **kwargs):
        def update_fil_file(file):
            """
            ！ 上传到对象存储
            :param file: b字节文件
            :return: 若成功返回文件路径，若不成功返回空
            """

            # 生成文件编号，如果文件名重复的话在oss中会覆盖之前的文件
            # 进度条
            # 当无法确定待上传的数据长度时，total_bytes的值为None。
            def percentage(consumed_bytes, total_bytes):
                if total_bytes:
                    rate = int(100 * (float(consumed_bytes) / float(total_bytes)))
                    print('\r{0}% '.format(rate), end='')

            number = uuid.uuid4()
            # 生成文件名
            base_file_name = file.name.split('.')[0] + '_' + str(number) + '.' + file.name.split('.')[1]
            # 生成外网访问的文件路径
            file_uri = base_file_url + base_file_name
            # 这个是阿里提供的SDK方法 bucket是调用的4.1中配置的变量名
            res = bucket.put_object(base_file_name, file.read(), progress_callback=percentage)
            # 如果上传状态是200 代表成功 返回文件外网访问路径
            # 下面代码根据自己的需求写
            if res.status == 200:
                return file_uri, file.name
            else:
                return False

        if request.method == 'POST':
            # 获取前端ajax传的文件 使用read()读取b字节文件
            file = request.FILES.get('file')
            # 通过上面封装的方法把文件上传
            file_url, base_fil_name = update_fil_file(file)
            if file_url:

                return JsonResponse(
                    {"code": 100, "message": "上传成功", 'data': {'file_name': base_fil_name, 'file_url': file_url}})
            else:
                return JsonResponse({"code": 300, "message": "oss上传失败"})
        else:
            return JsonResponse({"code": 300, "message": "错误的请求方式！"})
